package org.teremail.smtp;

import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.IoHandlerAdapter;
import org.apache.mina.common.IoSession;
import org.teremail.smtp.commands.SMTPCommand;

public class SMTPIOHandler extends IoHandlerAdapter {

    private SMTPCommandParser parser;
    private final DataConsumerFactory cf;
    private final static String MSG_500 = "500 Unrecognised command";
    private static final String MSG_220 = "220 Foomail server ready";

    public SMTPIOHandler(SMTPCommandParser commandParser, DataConsumerFactory cf) {
        this.parser = commandParser;
        this.cf = cf;
    }
    
    

    @Override
    public void sessionOpened(IoSession session) throws Exception {
        session.write(MSG_220);
    }



    @Override
    public void messageReceived(IoSession session, Object message) throws Exception {
        
        SMTPSession smtpSession = new MinaSMTPSession(session, "localhost");
        
        if (isDataMode(session)) {
            if (message instanceof ByteBuffer) {
                
                DataConsumer in = (DataConsumer) session.getAttribute(SessionAttributes.CONSUMER);
                if (in == null) {
                    in = cf.create(smtpSession);
                    session.setAttribute(SessionAttributes.CONSUMER, in);
                }
                
                in.write((ByteBuffer) message);
                
            } else {
                throw new Exception("Unexpected message type: " + message.getClass());
            }
        } else if (message instanceof String) {
            try {
                SMTPCommand cmd = parser.parse((String) message);
                cmd.process(smtpSession);
            } catch (UnknownCommandException e) {
                session.write(MSG_500);
            }
        } else {
            throw new Exception("Unexpected message type: " + message.getClass());
        }
        
    }

    private boolean isDataMode(IoSession session) {
        Boolean b = (Boolean) session.getAttribute(SessionAttributes.DATA_MODE);
        return b != null && b;
    }

    
}
